package org.proteored.miapeapi.xml;

import java.io.File;
import java.io.IOException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.proteored.miapeapi.exceptions.MiapeDatabaseException;
import org.proteored.miapeapi.exceptions.MiapeSecurityException;
import org.proteored.miapeapi.interfaces.Project;
import org.proteored.miapeapi.interfaces.persistence.PersistenceManager;
import org.proteored.miapeapi.interfaces.xml.AbstractProjectXmlFile;
import org.proteored.miapeapi.interfaces.xml.XmlProjectFactory;
import org.proteored.miapeapi.xml.miapeproject.ProjectImpl;
import org.proteored.miapeapi.xml.miapeproject.ProjectXmlFile;
import org.proteored.miapeapi.xml.miapeproject.adapter.ProjectAdapter;
import org.proteored.miapeapi.xml.miapeproject.autogenerated.MIAPEProject;

public class ProjectXmlFactory implements XmlProjectFactory {
	private static ProjectXmlFactory instance;
	private JAXBContext jc;

	private ProjectXmlFactory() {
		try {
			jc = JAXBContext.newInstance("org.proteored.miapeapi.xml.miapeproject.autogenerated");
		} catch (JAXBException e) {
			e.printStackTrace();
		}
	}

	public static ProjectXmlFactory getFactory() {
		if (instance == null) {
			instance = new ProjectXmlFactory();
		}
		return instance;
	}

	@Override
	public ProjectXmlFile toXml(Project project) {
		return getFactory().create(project);
	}

	@Override
	public Project toProject(AbstractProjectXmlFile xmlFile, PersistenceManager db, String userName, String password)
			throws MiapeDatabaseException, MiapeSecurityException, JAXBException {
		return getFactory().create(xmlFile, db, userName, password);
	}

	private Project create(AbstractProjectXmlFile xmlFile, PersistenceManager databaseManager, String userName,
			String password) throws MiapeDatabaseException, MiapeSecurityException, JAXBException {
		Project result = null;

		MIAPEProject projectXML = (MIAPEProject) jc.createUnmarshaller().unmarshal(xmlFile.toFile());
		if (databaseManager == null) {
			result = new ProjectImpl(projectXML, null, null);
		} else {
			result = new ProjectImpl(projectXML, databaseManager, userName, password);
		}

		return result;
	}

	private ProjectXmlFile create(Project project) {
		File xmlFile = null;
		try {
			xmlFile = File.createTempFile("projectXML", ".temp");
			MIAPEProject projectXML = new ProjectAdapter(project).adapt();
			Marshaller marshaller = jc.createMarshaller();
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true));

			try {
				marshaller.setProperty("com.sun.xml.bind.indentString", "\t");
			} catch (Exception e) {
				marshaller.setProperty("com.sun.xml.internal.bind.indentString", "\t");
			}
			marshaller.marshal(projectXML, xmlFile);
		} catch (JAXBException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return new ProjectXmlFile(xmlFile);
	}
}
